﻿using System;
using TaskManager.Domain.BusinessObjects;
using TaskManager.Domain.Exceptions;
using TaskManager.Domain.Repositories;

namespace TaskManager.Domain.Services
{
    /// <summary>
    /// Provides methods for <see cref="User"/> deletion
    /// </summary>
    internal class UserDeleteService : IUserDeleteService
    {
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(UserDeleteService));

        private readonly ITaskRepository _taskRepository;
        private readonly IUserRepository _userRepository;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="userRepository">Users repository</param>
        /// <param name="taskRepository">Tasks repository</param>
        public UserDeleteService(IUserRepository userRepository, ITaskRepository taskRepository)
        {
            _taskRepository = taskRepository;
            _userRepository = userRepository;
        }

        /// <summary>
        /// Deletes user
        /// </summary>
        /// <param name="user">User</param>
        /// <param name="commit">Lambda that will be invoked if user was successfully deleted in order to commit changes</param>
        /// <remarks>Since users are stored both in the application database and ASP.Net membership's database it is 
        /// recommended to commit changes in <c>commit</c> delegate</remarks>
        /// <example>
        /// userDeleteService.Delete("user1", () => _unitOfWork.Save());
        /// </example>
        /// <exception cref="UserActionFailureException">Thrown if user can not be deleted</exception>
        public void Delete(User user, Action commit)
        {
            if (Log.IsDebugEnabled) Log.Debug("Deleting user.User name=[" + user.Name + "]");

            Tuple<bool, string> validationResult = UserValidationRules.PermitDelete(user.Name, _taskRepository);

            if (!validationResult.Item1)
                throw new UserActionFailureException(validationResult.Item2);

            _userRepository.Delete(user.Id, commit);
        }

        /// <summary>
        /// Deletes user
        /// </summary>
        /// <param name="userId">User identifier in the database</param>
        /// <param name="commit">Lambda that will be invoked if user was successfully deleted in order to commit changes</param>
        /// <remarks>Since users are stored both in the application database and ASP.Net membership's database it is 
        /// recommended to commit changes in <c>commit</c> delegate</remarks>
        /// <example>
        /// userDeleteService.Delete(1, () => _unitOfWork.Save());
        /// </example>
        /// <exception cref="UserActionFailureException">Thrown if user can not be deleted</exception>
        public void Delete(int userId, Action commit)
        {
            User user = _userRepository.Find(userId);

            if(Log.IsDebugEnabled) Log.Debug("Deleting user.User name=[" + user.Name + "]");

            Tuple<bool, string> validationResult = UserValidationRules.PermitDelete(user.Name, _taskRepository);

            if (!validationResult.Item1)
                throw new UserActionFailureException(validationResult.Item2);

            _userRepository.Delete(userId, commit);
        }
    }
}